package com.smart.community.region.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.utils.StringUtils;
import com.smart.community.region.entity.Shop;
import com.smart.community.region.mapper.ShopMapper;
import com.smart.community.region.service.IShopService;
import com.smart.community.region.vo.ShopVO;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

/**
 * 店铺信息Service实现类
 * 
 * @author Wu.Liang
 * @version 1.0.0
 * @since 2025-09-30
 */
@Slf4j
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
    
    @Autowired
    private ShopMapper shopMapper;
    
    @Override
    @Cacheable(value = "shop:page", key = "#page.current + '_' + #page.size + '_' + #communityId + '_' + #shopType + '_' + #shopName + '_' + #shopCode + '_' + #buildingId + '_' + #unitId + '_' + #roomNumber + '_' + #contactPerson + '_' + #contactPhone + '_' + #status + '_' + #minArea + '_' + #maxArea + '_' + #minRentPrice + '_' + #maxRentPrice")
    public IPage<ShopVO> getShopPage(Page<ShopVO> page, Long communityId, Integer shopType, String shopName, String shopCode, Long buildingId, Long unitId, String roomNumber, String contactPerson, String contactPhone, Integer status, java.math.BigDecimal minArea, java.math.BigDecimal maxArea, java.math.BigDecimal minRentPrice, java.math.BigDecimal maxRentPrice) throws Exception {
        try {
            return shopMapper.selectShopPage(page, communityId, shopType, shopName, shopCode, buildingId, unitId, roomNumber, contactPerson, contactPhone, status, minArea, maxArea, minRentPrice, maxRentPrice);
        } catch (Exception e) {
            log.error("分页查询店铺列表失败，参数：communityId={}, shopType={}, shopName={}, shopCode={}, buildingId={}, unitId={}, roomNumber={}, contactPerson={}, contactPhone={}, status={}, minArea={}, maxArea={}, minRentPrice={}, maxRentPrice={}", 
                    communityId, shopType, shopName, shopCode, buildingId, unitId, roomNumber, contactPerson, contactPhone, status, minArea, maxArea, minRentPrice, maxRentPrice, e);
            throw new BusinessException("分页查询店铺列表失败：" + e.getMessage());
        }
    }
    
    
    @Override
    @Cacheable(value = "shop:list:community", key = "#communityId")
    public List<Shop> getShopListByCommunityId(Long communityId) throws Exception {
        try {
            if (communityId == null) {
                throw new BusinessException("社区ID不能为空");
            }
            return shopMapper.selectShopListByCommunityId(communityId);
        } catch (Exception e) {
            log.error("根据社区ID查询店铺列表失败，参数：communityId={}", communityId, e);
            throw new BusinessException("根据社区ID查询店铺列表失败：" + e.getMessage());
        }
    }
    
    @Override
    @Cacheable(value = "shop:list:type", key = "#shopType")
    public List<Shop> getShopListByType(Integer shopType) throws Exception {
        try {
            if (shopType == null) {
                throw new BusinessException("店铺类型不能为空");
            }
            return shopMapper.selectShopListByType(shopType);
        } catch (Exception e) {
            log.error("根据店铺类型查询店铺列表失败，参数：shopType={}", shopType, e);
            throw new BusinessException("根据店铺类型查询店铺列表失败：" + e.getMessage());
        }
    }
    
    @Override
    @Cacheable(value = "shop:detail:code", key = "#shopCode")
    public Shop getShopByCode(String shopCode) throws Exception {
        try {
            if (!StringUtils.isNotBlank(shopCode)) {
                throw new BusinessException("店铺编码不能为空");
            }
            return shopMapper.selectShopByCode(shopCode);
        } catch (Exception e) {
            log.error("根据店铺编码查询店铺信息失败，参数：shopCode={}", shopCode, e);
            throw new BusinessException("根据店铺编码查询店铺信息失败：" + e.getMessage());
        }
    }
    
    @Override
    @Cacheable(value = "shop:list:building", key = "#buildingId")
    public List<Shop> getShopListByBuildingId(Long buildingId) throws Exception {
        try {
            if (buildingId == null) {
                throw new BusinessException("楼栋ID不能为空");
            }
            return shopMapper.selectShopListByBuildingId(buildingId);
        } catch (Exception e) {
            log.error("根据楼栋ID查询店铺列表失败，参数：buildingId={}", buildingId, e);
            throw new BusinessException("根据楼栋ID查询店铺列表失败：" + e.getMessage());
        }
    }
    
    @Override
    @Cacheable(value = "shop:list:unit", key = "#unitId")
    public List<Shop> getShopListByUnitId(Long unitId) throws Exception {
        try {
            if (unitId == null) {
                throw new BusinessException("单元ID不能为空");
            }
            return shopMapper.selectShopListByUnitId(unitId);
        } catch (Exception e) {
            log.error("根据单元ID查询店铺列表失败，参数：unitId={}", unitId, e);
            throw new BusinessException("根据单元ID查询店铺列表失败：" + e.getMessage());
        }
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"shop:page", "shop:list:community", "shop:list:type", "shop:list:building", "shop:list:unit"}, allEntries = true)
    public Long createShop(Shop shop) throws Exception {
        try {
            // 自动生成店铺编码（32位随机字符串）
            String shopCode = generateUniqueShopCode();
            shop.setShopCode(shopCode);
            
            log.info("为店铺生成编码：{}，店铺名称：{}", shopCode, shop.getShopName());
            
            // 业务验证（在生成编码后进行）
            validateShop(shop);
            
            // 保存店铺信息
            boolean success = this.save(shop);
            if (!success) {
                throw new BusinessException("店铺创建失败");
            }
            
            log.info("店铺创建成功，店铺ID：{}，店铺名称：{}，店铺编码：{}", shop.getId(), shop.getShopName(), shop.getShopCode());
            return shop.getId();
        } catch (Exception e) {
            log.error("创建店铺失败，店铺信息：{}", shop, e);
            throw e;
        }
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"shop:page", "shop:list:community", "shop:list:type", "shop:list:building", "shop:list:unit", "shop:detail:code"}, allEntries = true)
    public Boolean updateShop(Shop shop) throws Exception {
        try {
            // 业务验证（编辑时不验证shopCode）
            validateShopForUpdate(shop);
            
            // 检查店铺是否存在
            Shop existingShop = this.getById(shop.getId());
            if (existingShop == null) {
                throw new BusinessException("店铺不存在，ID：" + shop.getId());
            }
            
            // 编辑店铺时不检查shopCode，保持原有编码
            // shopCode是创建时生成的唯一标识，编辑时不应修改
            
            // 更新店铺信息
            boolean success = this.updateById(shop);
            if (!success) {
                throw new BusinessException("店铺更新失败");
            }
            
            log.info("店铺更新成功，店铺ID：{}，店铺名称：{}", shop.getId(), shop.getShopName());
            return true;
        } catch (Exception e) {
            log.error("更新店铺失败，店铺信息：{}", shop, e);
            throw e;
        }
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"shop:page", "shop:list:community", "shop:list:type", "shop:list:building", "shop:list:unit", "shop:detail:code"}, allEntries = true)
    public Boolean deleteShop(Long id) throws Exception {
        try {
            if (id == null) {
                throw new BusinessException("店铺ID不能为空");
            }
            
            // 检查店铺是否存在
            Shop shop = this.getById(id);
            if (shop == null) {
                throw new BusinessException("店铺不存在，ID：" + id);
            }
            
            // 逻辑删除店铺
            boolean success = this.removeById(id);
            if (!success) {
                throw new BusinessException("店铺删除失败");
            }
            
            log.info("店铺删除成功，店铺ID：{}，店铺名称：{}", id, shop.getShopName());
            return true;
        } catch (Exception e) {
            log.error("删除店铺失败，店铺ID：{}", id, e);
            throw e;
        }
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"shop:page", "shop:list:community", "shop:list:type", "shop:list:building", "shop:list:unit", "shop:detail:code"}, allEntries = true)
    public Boolean batchDeleteShop(List<Long> ids) throws Exception {
        try {
            if (ids == null || ids.isEmpty()) {
                throw new BusinessException("店铺ID列表不能为空");
            }
            
            // 批量逻辑删除店铺
            boolean success = this.removeByIds(ids);
            if (!success) {
                throw new BusinessException("批量删除店铺失败");
            }
            
            log.info("批量删除店铺成功，店铺ID列表：{}", ids);
            return true;
        } catch (Exception e) {
            log.error("批量删除店铺失败，店铺ID列表：{}", ids, e);
            throw e;
        }
    }
    
    @Override
    @Cacheable(value = "shop:count", key = "#communityId + '_' + #shopType")
    public Integer countShops(Long communityId, Integer shopType) throws Exception {
        try {
            return shopMapper.countShops(communityId, shopType);
        } catch (Exception e) {
            log.error("统计店铺数量失败，参数：communityId={}, shopType={}", communityId, shopType, e);
            throw new BusinessException("统计店铺数量失败：" + e.getMessage());
        }
    }
    
    @Override
    public Boolean existsByShopCode(String shopCode, Long excludeId) throws Exception {
        try {
            if (!StringUtils.isNotBlank(shopCode)) {
                throw new BusinessException("店铺编码不能为空");
            }
            return shopMapper.existsByShopCode(shopCode, excludeId);
        } catch (Exception e) {
            log.error("检查店铺编码是否存在失败，参数：shopCode={}, excludeId={}", shopCode, excludeId, e);
            throw new BusinessException("检查店铺编码是否存在失败：" + e.getMessage());
        }
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"shop:page", "shop:list:community", "shop:list:type", "shop:list:building", "shop:list:unit", "shop:detail:code"}, allEntries = true)
    public Boolean enableShop(Long id) throws Exception {
        try {
            if (id == null) {
                throw new BusinessException("店铺ID不能为空");
            }
            
            // 检查店铺是否存在
            Shop shop = this.getById(id);
            if (shop == null) {
                throw new BusinessException("店铺不存在，ID：" + id);
            }
            
            // 启用店铺
            shop.setStatus(1);
            boolean success = this.updateById(shop);
            if (!success) {
                throw new BusinessException("启用店铺失败");
            }
            
            log.info("启用店铺成功，店铺ID：{}，店铺名称：{}", id, shop.getShopName());
            return true;
        } catch (Exception e) {
            log.error("启用店铺失败，店铺ID：{}", id, e);
            throw e;
        }
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"shop:page", "shop:list:community", "shop:list:type", "shop:list:building", "shop:list:unit", "shop:detail:code"}, allEntries = true)
    public Boolean disableShop(Long id) throws Exception {
        try {
            if (id == null) {
                throw new BusinessException("店铺ID不能为空");
            }
            
            // 检查店铺是否存在
            Shop shop = this.getById(id);
            if (shop == null) {
                throw new BusinessException("店铺不存在，ID：" + id);
            }
            
            // 禁用店铺
            shop.setStatus(0);
            boolean success = this.updateById(shop);
            if (!success) {
                throw new BusinessException("禁用店铺失败");
            }
            
            log.info("禁用店铺成功，店铺ID：{}，店铺名称：{}", id, shop.getShopName());
            return true;
        } catch (Exception e) {
            log.error("禁用店铺失败，店铺ID：{}", id, e);
            throw e;
        }
    }
    
    /**
     * 验证店铺信息
     * 
     * @param shop 店铺信息
     * @throws BusinessException 业务异常
     */
    private void validateShop(Shop shop) throws BusinessException {
        if (shop == null) {
            throw new BusinessException("店铺信息不能为空");
        }
        if (!StringUtils.isNotBlank(shop.getShopName())) {
            throw new BusinessException("店铺名称不能为空");
        }
        if (!StringUtils.isNotBlank(shop.getShopCode())) {
            throw new BusinessException("店铺编码不能为空");
        }
        if (shop.getShopType() == null) {
            throw new BusinessException("店铺类型不能为空");
        }
        if (shop.getCommunityId() == null) {
            throw new BusinessException("所属社区ID不能为空");
        }
        // 楼栋和单元字段为可选，不进行必填验证
        if (!StringUtils.isNotBlank(shop.getRoomNumber())) {
            throw new BusinessException("房间号不能为空");
        }
        if (shop.getArea() == null || shop.getArea().compareTo(java.math.BigDecimal.ZERO) <= 0) {
            throw new BusinessException("店铺面积必须大于0");
        }
        if (shop.getRentPrice() == null || shop.getRentPrice().compareTo(java.math.BigDecimal.ZERO) < 0) {
            throw new BusinessException("租金价格不能为负数");
        }
    }
    
    /**
     * 验证店铺信息（用于更新，不验证shopCode）
     * 
     * @param shop 店铺信息
     * @throws BusinessException 业务异常
     */
    private void validateShopForUpdate(Shop shop) throws BusinessException {
        if (shop == null) {
            throw new BusinessException("店铺信息不能为空");
        }
        if (!StringUtils.isNotBlank(shop.getShopName())) {
            throw new BusinessException("店铺名称不能为空");
        }
        // 编辑时不验证shopCode，保持原有编码
        if (shop.getShopType() == null) {
            throw new BusinessException("店铺类型不能为空");
        }
        if (shop.getCommunityId() == null) {
            throw new BusinessException("所属社区ID不能为空");
        }
        // 楼栋和单元字段为可选，不进行必填验证
        if (!StringUtils.isNotBlank(shop.getRoomNumber())) {
            throw new BusinessException("房间号不能为空");
        }
        if (shop.getArea() == null || shop.getArea().compareTo(java.math.BigDecimal.ZERO) <= 0) {
            throw new BusinessException("店铺面积必须大于0");
        }
        if (shop.getRentPrice() == null || shop.getRentPrice().compareTo(java.math.BigDecimal.ZERO) < 0) {
            throw new BusinessException("租金价格不能为负数");
        }
    }
    
    /**
     * 生成唯一的店铺编码
     * 
     * 使用32位随机字符串，确保唯一性
     * 
     * @return 唯一的店铺编码
     * @throws Exception 异常
     */
    private String generateUniqueShopCode() throws Exception {
        int maxAttempts = 10; // 最大尝试次数
        int attempts = 0;
        
        while (attempts < maxAttempts) {
            // 生成32位随机字符串
            String shopCode = java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 32);
            
            // 检查编码是否已存在
            if (!existsByShopCode(shopCode, null)) {
                log.info("生成唯一店铺编码成功：{}，尝试次数：{}", shopCode, attempts + 1);
                return shopCode;
            }
            
            attempts++;
            log.warn("店铺编码已存在，重新生成：{}，尝试次数：{}", shopCode, attempts);
        }
        
        throw new BusinessException("生成唯一店铺编码失败，已尝试" + maxAttempts + "次");
    }
}
